package com.freedom.monitor.myeye.metrics.server.handler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import static io.netty.handler.codec.http.HttpMethod.*;
import static io.netty.handler.codec.http.HttpResponseStatus.*;
import static io.netty.handler.codec.http.HttpVersion.*;

import com.freedom.monitor.myeye.metrics.server.pool.StorageExecutorPool;
import com.freedom.monitor.myeye.metrics.server.utils.NettyUtils;
import com.freedom.rpc.thrift.common.utils.Logger;

public class HttpUserHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
	// logger
	private static final Logger logger = Logger.getLogger(HttpUserHandler.class);
	public static String REPORT_URI = "/metrics";

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
		// 注解:token未检验,应该放到header中来做,还是为了性能
		// 1)保证解析结果正确,否则一切无从谈起
		if (!request.getDecoderResult().isSuccess()) {
			NettyUtils.sendError(ctx, BAD_REQUEST);
			return;
		}
		// 2)确保方法是我们需要的(目前只支持GET | POST | PUT | HEAD ,其它不支持)
		if (POST != request.getMethod()) {
			NettyUtils.sendError(ctx, METHOD_NOT_ALLOWED);
			return;
		}
		// 3)uri是有长度的,暂且不对uri进行check,有需要的话，用户自己实现
		final String uri = request.getUri();
		if (uri == null || uri.trim().length() == 0 || false == uri.equals(REPORT_URI)) {
			NettyUtils.sendError(ctx, FORBIDDEN);
			return;
		}
		// 4)提取数据,提交给DB线程池,这样可以提交到HBase
		ByteBuf content = request.content();
		byte[] bytes = new byte[content.readableBytes()];
		content.readBytes(bytes);
		String data = new String(bytes);
		logger.debug(data);
		//
		// 5)一切就绪,告诉前端顺利接收了,我们不接受长连接,所以一旦发送响应完毕就立刻关闭连接
		StorageExecutorPool.execute(data);// 一次性提交到RPC服务器那边,否则网络实在耗不起
		FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
		ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		logger.error(cause.toString());
		ctx.close();
	}

}
